home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / editors / stevie3a.3 < prev    next >
Text File  |  1989-03-15  |  61KB  |  2,492 lines

  1. Path: xanth!ukma!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i042:  stevie - vi-like text editor v35a, Part03/06
  5. Message-ID: <12215@swan.ulowell.edu>
  6. Date: 15 Mar 89 14:57:35 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2481
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: grwalter@watcgl.waterloo.edu (Fred Walter)
  12. Posting-number: Volume 89, Issue 42
  13. Archive-name: editors/stevie35a.3
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    charset.c
  23. #    edit.c
  24. #    help.c
  25. #    main.c
  26. #    misccmds.c
  27. #    screen.c
  28. # This archive created: Tue Mar 14 14:41:34 1989
  29. cat << \SHAR_EOF > charset.c
  30. /*
  31.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  32.  *
  33.  * Code Contributions By : Tim Thompson           twitch!tjt
  34.  *                         Tony Andrews           onecom!wldrdg!tony 
  35.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  36.  */
  37.  
  38. #include "stevie.h"
  39.  
  40. /*
  41.  * This file shows how to display characters on the screen. This is approach
  42.  * is something of an overkill. It's a remnant from the original code that
  43.  * isn't worth messing with for now. TABS are special-cased depending on the
  44.  * value of the "list" parameter. 
  45.  */
  46.  
  47. struct charinfo chars[] = {
  48.                 /* 0 */ 1, NUL,
  49.                 /* 1 */ 2, "^A",
  50.                 /* 2 */ 2, "^B",
  51.                 /* 3 */ 2, "^C",
  52.                 /* 4 */ 2, "^D",
  53.                 /* 5 */ 2, "^E",
  54.                 /* 6 */ 2, "^F",
  55.                 /* 7 */ 2, "^G",
  56.                 /* 8 */ 2, "^H",
  57.                 /* 9 */ 2, "^I",
  58.                 /* 10 */ 7, "[ERROR]",    /* shouldn't happen */
  59.                 /* 11 */ 2, "^K",
  60.                 /* 12 */ 2, "^L",
  61.                 /* 13 */ 2, "^M",
  62.                 /* 14 */ 2, "^N",
  63.                 /* 15 */ 2, "^O",
  64.                 /* 16 */ 2, "^P",
  65.                 /* 17 */ 2, "^Q",
  66.                 /* 18 */ 2, "^R",
  67.                 /* 19 */ 2, "^S",
  68.                 /* 20 */ 2, "^T",
  69.                 /* 21 */ 2, "^U",
  70.                 /* 22 */ 2, "^V",
  71.                 /* 23 */ 2, "^W",
  72.                 /* 24 */ 2, "^X",
  73.                 /* 25 */ 2, "^Y",
  74.                 /* 26 */ 2, "^Z",
  75.                 /* 27 */ 2, "^[",
  76.                 /* 28 */ 2, "^\\",
  77.                 /* 29 */ 2, "^]",
  78.                 /* 30 */ 2, "^^",
  79.                 /* 31 */ 2, "^_",
  80.                 /* 32 */ 1, " ",
  81.                 /* 33 */ 1, "!",
  82.                 /* 34 */ 1, "\"",
  83.                 /* 35 */ 1, "#",
  84.                 /* 36 */ 1, "$",
  85.                 /* 37 */ 1, "%",
  86.                 /* 38 */ 1, "&",
  87.                 /* 39 */ 1, "'",
  88.                 /* 40 */ 1, "(",
  89.                 /* 41 */ 1, ")",
  90.                 /* 42 */ 1, "*",
  91.                 /* 43 */ 1, "+",
  92.                 /* 44 */ 1, ",",
  93.                 /* 45 */ 1, "-",
  94.                 /* 46 */ 1, ".",
  95.                 /* 47 */ 1, "/",
  96.                 /* 48 */ 1, "0",
  97.                 /* 49 */ 1, "1",
  98.                 /* 50 */ 1, "2",
  99.                 /* 51 */ 1, "3",
  100.                 /* 52 */ 1, "4",
  101.                 /* 53 */ 1, "5",
  102.                 /* 54 */ 1, "6",
  103.                 /* 55 */ 1, "7",
  104.                 /* 56 */ 1, "8",
  105.                 /* 57 */ 1, "9",
  106.                 /* 58 */ 1, ":",
  107.                 /* 59 */ 1, ";",
  108.                 /* 60 */ 1, "<",
  109.                 /* 61 */ 1, "=",
  110.                 /* 62 */ 1, ">",
  111.                 /* 63 */ 1, "?",
  112.                 /* 64 */ 1, "@",
  113.                 /* 65 */ 1, "A",
  114.                 /* 66 */ 1, "B",
  115.                 /* 67 */ 1, "C",
  116.                 /* 68 */ 1, "D",
  117.                 /* 69 */ 1, "E",
  118.                 /* 70 */ 1, "F",
  119.                 /* 71 */ 1, "G",
  120.                 /* 72 */ 1, "H",
  121.                 /* 73 */ 1, "I",
  122.                 /* 74 */ 1, "J",
  123.                 /* 75 */ 1, "K",
  124.                 /* 76 */ 1, "L",
  125.                 /* 77 */ 1, "M",
  126.                 /* 78 */ 1, "N",
  127.                 /* 79 */ 1, "O",
  128.                 /* 80 */ 1, "P",
  129.                 /* 81 */ 1, "Q",
  130.                 /* 82 */ 1, "R",
  131.                 /* 83 */ 1, "S",
  132.                 /* 84 */ 1, "T",
  133.                 /* 85 */ 1, "U",
  134.                 /* 86 */ 1, "V",
  135.                 /* 87 */ 1, "W",
  136.                 /* 88 */ 1, "X",
  137.                 /* 89 */ 1, "Y",
  138.                 /* 90 */ 1, "Z",
  139.                 /* 91 */ 1, "[",
  140.                 /* 92 */ 1, "\\",
  141.                 /* 93 */ 1, "]",
  142.                 /* 94 */ 1, "^",
  143.                 /* 95 */ 1, "_",
  144.                 /* 96 */ 1, "`",
  145.                 /* 97 */ 1, "a",
  146.                 /* 98 */ 1, "b",
  147.                 /* 99 */ 1, "c",
  148.                 /* 100 */ 1, "d",
  149.                 /* 101 */ 1, "e",
  150.                 /* 102 */ 1, "f",
  151.                 /* 103 */ 1, "g",
  152.                 /* 104 */ 1, "h",
  153.                 /* 105 */ 1, "i",
  154.                 /* 106 */ 1, "j",
  155.                 /* 107 */ 1, "k",
  156.                 /* 108 */ 1, "l",
  157.                 /* 109 */ 1, "m",
  158.                 /* 110 */ 1, "n",
  159.                 /* 111 */ 1, "o",
  160.                 /* 112 */ 1, "p",
  161.                 /* 113 */ 1, "q",
  162.                 /* 114 */ 1, "r",
  163.                 /* 115 */ 1, "s",
  164.                 /* 116 */ 1, "t",
  165.                 /* 117 */ 1, "u",
  166.                 /* 118 */ 1, "v",
  167.                 /* 119 */ 1, "w",
  168.                 /* 120 */ 1, "x",
  169.                 /* 121 */ 1, "y",
  170.                 /* 122 */ 1, "z",
  171.                 /* 123 */ 1, "{",
  172.                 /* 124 */ 1, "|",
  173.                 /* 125 */ 1, "}",
  174.                 /* 126 */ 1, "~",
  175.                 /* 127 */ 2, "^?",
  176.                 /* 128 */ 5, "[128]",
  177.                 /* 129 */ 5, "[129]",
  178.                 /* 130 */ 5, "[130]",
  179.                 /* 131 */ 5, "[131]",
  180.                 /* 132 */ 5, "[132]",
  181.                 /* 133 */ 5, "[133]",
  182.                 /* 134 */ 5, "[134]",
  183.                 /* 135 */ 5, "[135]",
  184.                 /* 136 */ 5, "[136]",
  185.                 /* 137 */ 5, "[137]",
  186.                 /* 138 */ 5, "[138]",
  187.                 /* 139 */ 5, "[139]",
  188.                 /* 140 */ 5, "[140]",
  189.                 /* 141 */ 5, "[141]",
  190.                 /* 142 */ 5, "[142]",
  191.                 /* 143 */ 5, "[143]",
  192.                 /* 144 */ 5, "[144]",
  193.                 /* 145 */ 5, "[145]",
  194.                 /* 146 */ 5, "[146]",
  195.                 /* 147 */ 5, "[147]",
  196.                 /* 148 */ 5, "[148]",
  197.                 /* 149 */ 5, "[149]",
  198.                 /* 150 */ 5, "[150]",
  199.                 /* 151 */ 5, "[151]",
  200.                 /* 152 */ 5, "[152]",
  201.                 /* 153 */ 5, "[153]",
  202.                 /* 154 */ 5, "[154]",
  203.                 /* 155 */ 5, "[155]",
  204.                 /* 156 */ 5, "[156]",
  205.                 /* 157 */ 5, "[157]",
  206.                 /* 158 */ 5, "[158]",
  207.                 /* 159 */ 5, "[159]",
  208. #ifdef AMIGA
  209.                 /* 160 */ 1, "\240",
  210.                 /* 161 */ 1, "\241",
  211.                 /* 162 */ 1, "\242",
  212.                 /* 163 */ 1, "\243",
  213.                 /* 164 */ 1, "\244",
  214.                 /* 165 */ 1, "\245",
  215.                 /* 166 */ 1, "\246",
  216.                 /* 167 */ 1, "\247",
  217.                 /* 168 */ 1, "\250",
  218.                 /* 169 */ 1, "\251",
  219.                 /* 170 */ 1, "\252",
  220.                 /* 171 */ 1, "\253",
  221.                 /* 172 */ 1, "\254",
  222.                 /* 173 */ 1, "\255",
  223.                 /* 174 */ 1, "\256",
  224.                 /* 175 */ 1, "\257",
  225.                 /* 176 */ 1, "\260",
  226.                 /* 177 */ 1, "\261",
  227.                 /* 178 */ 1, "\262",
  228.                 /* 179 */ 1, "\263",
  229.                 /* 180 */ 1, "\264",
  230.                 /* 181 */ 1, "\265",
  231.                 /* 182 */ 1, "\266",
  232.                 /* 183 */ 1, "\267",
  233.                 /* 184 */ 1, "\270",
  234.                 /* 185 */ 1, "\271",
  235.                 /* 186 */ 1, "\272",
  236.                 /* 187 */ 1, "\273",
  237.                 /* 188 */ 1, "\274",
  238.                 /* 189 */ 1, "\275",
  239.                 /* 190 */ 1, "\276",
  240.                 /* 191 */ 1, "\277",
  241.                 /* 192 */ 1, "\300",
  242.                 /* 193 */ 1, "\301",
  243.                 /* 194 */ 1, "\302",
  244.                 /* 195 */ 1, "\303",
  245.                 /* 196 */ 1, "\304",
  246.                 /* 197 */ 1, "\305",
  247.                 /* 198 */ 1, "\306",
  248.                 /* 199 */ 1, "\307",
  249.                 /* 200 */ 1, "\310",
  250.                 /* 201 */ 1, "\311",
  251.                 /* 202 */ 1, "\312",
  252.                 /* 203 */ 1, "\313",
  253.                 /* 204 */ 1, "\314",
  254.                 /* 205 */ 1, "\315",
  255.                 /* 206 */ 1, "\316",
  256.                 /* 207 */ 1, "\317",
  257.                 /* 208 */ 1, "\320",
  258.                 /* 209 */ 1, "\321",
  259.                 /* 210 */ 1, "\322",
  260.                 /* 211 */ 1, "\323",
  261.                 /* 212 */ 1, "\324",
  262.                 /* 213 */ 1, "\325",
  263.                 /* 214 */ 1, "\326",
  264.                 /* 215 */ 1, "\327",
  265.                 /* 216 */ 1, "\330",
  266.                 /* 217 */ 1, "\331",
  267.                 /* 218 */ 1, "\332",
  268.                 /* 219 */ 1, "\333",
  269.                 /* 220 */ 1, "\334",
  270.                 /* 221 */ 1, "\335",
  271.                 /* 222 */ 1, "\336",
  272.                 /* 223 */ 1, "\337",
  273.                 /* 224 */ 1, "\340",
  274.                 /* 225 */ 1, "\341",
  275.                 /* 226 */ 1, "\342",
  276.                 /* 227 */ 1, "\343",
  277.                 /* 228 */ 1, "\344",
  278.                 /* 229 */ 1, "\345",
  279.                 /* 230 */ 1, "\346",
  280.                 /* 231 */ 1, "\347",
  281.                 /* 232 */ 1, "\350",
  282.                 /* 233 */ 1, "\351",
  283.                 /* 234 */ 1, "\352",
  284.                 /* 235 */ 1, "\353",
  285.                 /* 236 */ 1, "\354",
  286.                 /* 237 */ 1, "\355",
  287.                 /* 238 */ 1, "\356",
  288.                 /* 239 */ 1, "\357",
  289.                 /* 240 */ 1, "\360",
  290.                 /* 241 */ 1, "\361",
  291.                 /* 242 */ 1, "\362",
  292.                 /* 243 */ 1, "\363",
  293.                 /* 244 */ 1, "\364",
  294.                 /* 245 */ 1, "\365",
  295.                 /* 246 */ 1, "\366",
  296.                 /* 247 */ 1, "\367",
  297.                 /* 248 */ 1, "\370",
  298.                 /* 249 */ 1, "\371",
  299.                 /* 250 */ 1, "\372",
  300.                 /* 251 */ 1, "\373",
  301.                 /* 252 */ 1, "\374",
  302.                 /* 253 */ 1, "\375",
  303.                 /* 254 */ 1, "\376",
  304.                 /* 255 */ 1, "\377"
  305. #else
  306.                 /* 160 */ 5, "[160]",
  307.                 /* 161 */ 5, "[161]",
  308.                 /* 162 */ 5, "[162]",
  309.                 /* 163 */ 5, "[163]",
  310.                 /* 164 */ 5, "[164]",
  311.                 /* 165 */ 5, "[165]",
  312.                 /* 166 */ 5, "[166]",
  313.                 /* 167 */ 5, "[167]",
  314.                 /* 168 */ 5, "[168]",
  315.                 /* 169 */ 5, "[169]",
  316.                 /* 170 */ 5, "[170]",
  317.                 /* 171 */ 5, "[171]",
  318.                 /* 172 */ 5, "[172]",
  319.                 /* 173 */ 5, "[173]",
  320.                 /* 174 */ 5, "[174]",
  321.                 /* 175 */ 5, "[175]",
  322.                 /* 176 */ 5, "[176]",
  323.                 /* 177 */ 5, "[177]",
  324.                 /* 178 */ 5, "[178]",
  325.                 /* 179 */ 5, "[179]",
  326.                 /* 180 */ 5, "[180]",
  327.                 /* 181 */ 5, "[181]",
  328.                 /* 182 */ 5, "[182]",
  329.                 /* 183 */ 5, "[183]",
  330.                 /* 184 */ 5, "[184]",
  331.                 /* 185 */ 5, "[185]",
  332.                 /* 186 */ 5, "[186]",
  333.                 /* 187 */ 5, "[187]",
  334.                 /* 188 */ 5, "[188]",
  335.                 /* 189 */ 5, "[189]",
  336.                 /* 190 */ 5, "[190]",
  337.                 /* 191 */ 5, "[191]",
  338.                 /* 192 */ 5, "[192]",
  339.                 /* 193 */ 5, "[193]",
  340.                 /* 194 */ 5, "[194]",
  341.                 /* 195 */ 5, "[195]",
  342.                 /* 196 */ 5, "[196]",
  343.                 /* 197 */ 5, "[197]",
  344.                 /* 198 */ 5, "[198]",
  345.                 /* 199 */ 5, "[199]",
  346.                 /* 200 */ 5, "[200]",
  347.                 /* 201 */ 5, "[201]",
  348.                 /* 202 */ 5, "[202]",
  349.                 /* 203 */ 5, "[203]",
  350.                 /* 204 */ 5, "[204]",
  351.                 /* 205 */ 5, "[205]",
  352.                 /* 206 */ 5, "[206]",
  353.                 /* 207 */ 5, "[207]",
  354.                 /* 208 */ 5, "[208]",
  355.                 /* 209 */ 5, "[209]",
  356.                 /* 210 */ 5, "[210]",
  357.                 /* 211 */ 5, "[211]",
  358.                 /* 212 */ 5, "[212]",
  359.                 /* 213 */ 5, "[213]",
  360.                 /* 214 */ 5, "[214]",
  361.                 /* 215 */ 5, "[215]",
  362.                 /* 216 */ 5, "[216]",
  363.                 /* 217 */ 5, "[217]",
  364.                 /* 218 */ 5, "[218]",
  365.                 /* 219 */ 5, "[219]",
  366.                 /* 220 */ 5, "[220]",
  367.                 /* 221 */ 5, "[221]",
  368.                 /* 222 */ 5, "[222]",
  369.                 /* 223 */ 5, "[223]",
  370.                 /* 224 */ 5, "[224]",
  371.                 /* 225 */ 5, "[225]",
  372.                 /* 226 */ 5, "[226]",
  373.                 /* 227 */ 5, "[227]",
  374.                 /* 228 */ 5, "[228]",
  375.                 /* 229 */ 5, "[229]",
  376.                 /* 230 */ 5, "[230]",
  377.                 /* 231 */ 5, "[231]",
  378.                 /* 232 */ 5, "[232]",
  379.                 /* 233 */ 5, "[233]",
  380.                 /* 234 */ 5, "[234]",
  381.                 /* 235 */ 5, "[235]",
  382.                 /* 236 */ 5, "[236]",
  383.                 /* 237 */ 5, "[237]",
  384.                 /* 238 */ 5, "[238]",
  385.                 /* 239 */ 5, "[239]",
  386.                 /* 240 */ 5, "[240]",
  387.                 /* 241 */ 5, "[241]",
  388.                 /* 242 */ 5, "[242]",
  389.                 /* 243 */ 5, "[243]",
  390.                 /* 244 */ 5, "[244]",
  391.                 /* 245 */ 5, "[245]",
  392.                 /* 246 */ 5, "[246]",
  393.                 /* 247 */ 5, "[247]",
  394.                 /* 248 */ 5, "[248]",
  395.                 /* 249 */ 5, "[249]",
  396.                 /* 250 */ 5, "[250]",
  397.                 /* 251 */ 5, "[251]",
  398.                 /* 252 */ 5, "[252]",
  399.                 /* 253 */ 5, "[253]",
  400.                 /* 254 */ 5, "[254]",
  401.                 /* 255 */ 5, "[255]"
  402. #endif
  403. };
  404. SHAR_EOF
  405. cat << \SHAR_EOF > edit.c
  406. /*
  407.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  408.  *
  409.  * Code Contributions By : Tim Thompson           twitch!tjt
  410.  *                         Tony Andrews           onecom!wldrdg!tony 
  411.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  412.  */
  413.  
  414. #include "stevie.h"
  415.  
  416. /*
  417.  * This flag is used to make auto-indent work right on lines where only a
  418.  * <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
  419.  * reset when any other editting is done on the line. If an <ESC> or <RETURN>
  420.  * is received, and did_ai is TRUE, the line is truncated. 
  421.  */
  422. bool_t          did_ai = FALSE;
  423.  
  424. void
  425. edit()
  426. {
  427.     char            c;
  428.     bool_t          literal_next_flag = FALSE;
  429.  
  430.     Prenum = 0;
  431.  
  432.     /* position the display and the cursor at the top of the file. */
  433.     *Topchar = *Filemem;
  434.     *Curschar = *Filemem;
  435.     Cursrow = Curscol = 0;
  436.  
  437.     for (;;) {
  438.  
  439.     if (!RedrawingDisabled) {
  440.         cursupdate();    /* Figure out where the cursor is based on
  441.                  * Curschar. */
  442.         if (MustRedrawLine)
  443.         redrawline();
  444.  
  445.         if (MustRedrawScreen)
  446.         updateRealscreen();
  447.  
  448.         windgoto(Cursrow, Curscol);
  449.     }
  450.     c = vgetc();
  451.  
  452.     if (State == NORMAL) {
  453.         /* We're in the normal (non-insert) mode. */
  454.  
  455.         /* Pick up any leading digits and compute 'Prenum' */
  456.         if ((Prenum > 0 && isdigit(c)) || (isdigit(c) && c != '0')) {
  457.         Prenum = Prenum * 10 + (c - '0');
  458.         continue;
  459.         }
  460.         /* execute the command */
  461.         normal(c);
  462.         Prenum = 0;
  463.  
  464.     } else {
  465.         if (c == CTRL('V') && !literal_next_flag) {
  466.         literal_next_flag = TRUE;
  467.         outchar('^');
  468.         continue;
  469.         }
  470.         if (literal_next_flag) {
  471.         literal_next_flag = FALSE;
  472.         outchar('\b');
  473.         if (c != NL) {
  474.             did_ai = FALSE;
  475.             insertchar(c);
  476.             continue;
  477.         }
  478.         }
  479.         switch (c) {    /* We're in insert mode */
  480.  
  481.           case ESC:    /* an escape ends input mode */
  482.     doESCkey:
  483.         /*
  484.          * If we just did an auto-indent, truncate the line, and put
  485.          * the cursor back. 
  486.          */
  487.         if (did_ai) {
  488.             Curschar->linep->s[0] = NUL;
  489.             Curschar->index = 0;
  490.             did_ai = FALSE;
  491.         }
  492.         set_want_col = TRUE;
  493.  
  494.         /*
  495.          * The cursor should end up on the last inserted character.
  496.          * This is an attempt to match the real 'vi', but it may not
  497.          * be quite right yet. 
  498.          */
  499.         if (Curschar->index != 0) {
  500.             if (gchar(Curschar) == NUL)
  501.             dec(Curschar);
  502.             else if (Insbuffptr != NULL)
  503.             dec(Curschar);
  504.         }
  505.         State = NORMAL;
  506.         msg("");
  507.  
  508.         if (RedrawingDisabled) {
  509.             updateNextscreen(NOT_VALID);    /* Update LineSizes. */
  510.             cursupdate();    /* Update Topchar and Botchar. */
  511.         }
  512.         if (!UndoInProgress) {
  513.             int             n;
  514.             char           *p;
  515.  
  516.             if (last_command == 'o')
  517.             AppendToUndobuff(UNDO_SHIFTJ_STR);
  518.  
  519.             if (Insbuffptr != NULL) {
  520.             if (last_command == 'O')
  521.                 AppendToUndobuff("0");
  522.             AppendToRedobuff(Insbuff);
  523.             AppendToUndoUndobuff(Insbuff);
  524.             n = 0;
  525.             for (p = Insbuff; *p != NUL; p++) {
  526.                 if (*p == NL) {
  527.                 if (n) {
  528.                     AppendNumberToUndobuff(n);
  529.                     AppendToUndobuff("dl");
  530.                     n = 0;
  531.                 }
  532.                 AppendToUndobuff(UNDO_SHIFTJ_STR);
  533.                 } else
  534.                 n++;
  535.             }
  536.             if (n) {
  537.                 AppendNumberToUndobuff(n);
  538.                 AppendToUndobuff("dl");
  539.             }
  540.             }
  541.             if (last_command == 'c') {
  542.             AppendToUndobuff(mkstr(last_command_char));
  543.             AppendToUndobuff(Yankbuff);
  544.             AppendToUndobuff(ESC_STR);
  545.             }
  546.             AppendToRedobuff(ESC_STR);
  547.             AppendToUndoUndobuff(ESC_STR);
  548.             if (last_command == 'O')
  549.             AppendToUndobuff(UNDO_SHIFTJ_STR);
  550.         }
  551.         break;
  552.  
  553.           case CTRL('D'):
  554.         /*
  555.          * Control-D is treated as a backspace in insert mode to make
  556.          * auto-indent easier. This isn't completely compatible with
  557.          * vi, but it's a lot easier than doing it exactly right, and
  558.          * the difference isn't very noticeable. 
  559.          */
  560.           case BS:
  561.         /* can't backup past starting point */
  562.         if (Curschar->linep == Insstart->linep &&
  563.             Curschar->index <= Insstart->index) {
  564.             beep();
  565.             break;
  566.         }
  567.         /* can't backup to a previous line */
  568.         if (Curschar->linep != Insstart->linep &&
  569.             Curschar->index <= 0) {
  570.             beep();
  571.             break;
  572.         }
  573.         did_ai = FALSE;
  574.         dec(Curschar);
  575.         delchar(TRUE, FALSE);
  576.         /*
  577.          * It's a little strange to put backspaces into the redo
  578.          * buffer, but it makes auto-indent a lot easier to deal
  579.          * with. 
  580.          */
  581.         AppendToInsbuff(BS_STR);
  582.         if (!RedrawingDisabled) {
  583.             cursupdate();
  584.             updateline();
  585.         }
  586.         break;
  587.  
  588.           case CR:
  589.           case NL:
  590.         AppendToInsbuff(NL_STR);
  591.         if (!OpenForward(!RedrawingDisabled))
  592.             goto doESCkey;    /* out of memory */
  593.  
  594.         if (!RedrawingDisabled)
  595.             windgoto(Cursrow, Curscol);
  596.         break;
  597.  
  598.           default:
  599.         did_ai = FALSE;
  600.         insertchar(c);
  601.         break;
  602.         }
  603.     }
  604.     }
  605. }
  606.  
  607. /*
  608.  * Special characters in this context are those that need processing other
  609.  * than the simple insertion that can be performed here. This includes ESC
  610.  * which terminates the insert, and CR/NL which need special processing to
  611.  * open up a new line. This routine tries to optimize insertions performed by
  612.  * the "redo", "undo" or "put" commands, so it needs to know when it should
  613.  * stop and defer processing to the "normal" mechanism. 
  614.  */
  615. #define    ISSPECIAL(c)    ((c) == BS || (c) == NL || (c) == CR || (c) == ESC)
  616.  
  617. void
  618. insertchar(c)
  619.     char            c;
  620. {
  621.     if (anyinput()) {        /* If there's any pending input, grab up to
  622.                  * MAX_COLUMNS at once. */
  623.     char            p[MAX_COLUMNS + 1];
  624.     int             i;
  625.  
  626.     p[0] = c;
  627.     i = 1;
  628.     c = vpeekc();
  629.     while (!ISSPECIAL(c) && anyinput() && (i < MAX_COLUMNS)) {
  630.         p[i++] = vgetc();
  631.         c = vpeekc();
  632.     }
  633.     p[i] = '\0';
  634.     insstr(p);
  635.     AppendToInsbuff(p);
  636.     } else {
  637.     inschar(c);
  638.     AppendToInsbuff(mkstr(c));
  639.     }
  640.  
  641.     if (!RedrawingDisabled)
  642.     updateline();
  643. }
  644.  
  645. void
  646. getout(r)
  647.     int             r;
  648. {
  649.     windgoto(Rows - 1, 0);
  650.     putchar('\r');
  651.     putchar('\n');
  652.     windexit(r);
  653. }
  654.  
  655. void
  656. scrolldown(nlines)
  657.     int             nlines;
  658. {
  659.     register LPtr  *p;
  660.     register int    done = 0;    /* total # of physical lines done */
  661.  
  662.     /* Scroll up 'nlines' lines. */
  663.     while (nlines--) {
  664.     if ((p = prevline(Topchar)) == NULL)
  665.         break;
  666.     done += plines(p);
  667.     *Topchar = *p;
  668.     if (Curschar->linep == Botchar->linep->prev)
  669.         *Curschar = *prevline(Curschar);
  670.     }
  671.     s_ins(0, done, Rows, Columns);
  672. }
  673.  
  674. void
  675. scrollup(nlines)
  676.     int             nlines;
  677. {
  678.     register LPtr  *p;
  679.     register int    done = 0;    /* total # of physical lines done */
  680.     register int    pl;        /* # of plines for the current line */
  681.  
  682.     /* Scroll down 'nlines' lines. */
  683.     while (nlines--) {
  684.     pl = plines(Topchar);
  685.     if ((p = nextline(Topchar)) == NULL)
  686.         break;
  687.     done += pl;
  688.     if (Curschar->linep == Topchar->linep)
  689.         *Curschar = *p;
  690.     *Topchar = *p;
  691.  
  692.     }
  693.     s_del(0, done, Rows, Columns);
  694. }
  695.  
  696. /*
  697.  * oneright oneleft onedown oneup 
  698.  *
  699.  * Move one char {right,left,down,up}.  Return TRUE when sucessful, FALSE when
  700.  * we hit a boundary (of a line, or the file). 
  701.  */
  702.  
  703. bool_t
  704. oneright()
  705. {
  706.     set_want_col = TRUE;
  707.  
  708.     switch (inc(Curschar)) {
  709.  
  710.       case 0:
  711.     return TRUE;
  712.  
  713.       case 1:
  714.     dec(Curschar);        /* crossed a line, so back up */
  715.     /* FALLTHROUGH */
  716.       case -1:
  717.     return FALSE;
  718.     }
  719.  
  720.     return FALSE;        /* PARANOIA: should never reach here */
  721. }
  722.  
  723. bool_t
  724. oneleft()
  725. {
  726.     set_want_col = TRUE;
  727.  
  728.     switch (dec(Curschar)) {
  729.  
  730.       case 0:
  731.     return TRUE;
  732.  
  733.       case 1:
  734.     inc(Curschar);        /* crossed a line, so back up */
  735.     /* FALLTHROUGH */
  736.       case -1:
  737.     return FALSE;
  738.     }
  739.  
  740.     return FALSE;        /* PARANOIA: should never reach here */
  741. }
  742.  
  743. void
  744. beginline(flag)
  745.     bool_t          flag;
  746. {
  747.     while (oneleft());
  748.     if (flag) {
  749.     while (isspace(gchar(Curschar)) && oneright());
  750.     }
  751.     set_want_col = TRUE;
  752. }
  753.  
  754. bool_t
  755. oneup(n)
  756. {
  757.     LPtr            p, *np;
  758.     int             k;
  759.  
  760.     p = *Curschar;
  761.     for (k = 0; k < n; k++) {
  762.     /* Look for the previous line */
  763.     if ((np = prevline(&p)) == NULL) {
  764.         /* If we've at least backed up a little .. */
  765.         if (k > 0)
  766.         break;        /* to update the cursor, etc. */
  767.         else
  768.         return FALSE;
  769.     }
  770.     p = *np;
  771.     }
  772.     *Curschar = p;
  773.  
  774.     cursupdate();        /* make sure Topchar is valid */
  775.  
  776.     /* try to advance to the column we want to be at */
  777.     *Curschar = *coladvance(&p, Curswant);
  778.     return TRUE;
  779. }
  780.  
  781. bool_t
  782. onedown(n)
  783. {
  784.     LPtr            p, *np;
  785.     int             k;
  786.  
  787.     p = *Curschar;
  788.     for (k = 0; k < n; k++) {
  789.     /* Look for the next line */
  790.     if ((np = nextline(&p)) == NULL) {
  791.         if (k > 0)
  792.         break;
  793.         else
  794.         return FALSE;
  795.     }
  796.     p = *np;
  797.     }
  798.  
  799.     cursupdate();        /* make sure Topchar is valid */
  800.  
  801.     /* try to advance to the column we want to be at */
  802.     *Curschar = *coladvance(&p, Curswant);
  803.     return TRUE;
  804. }
  805. SHAR_EOF
  806. cat << \SHAR_EOF > help.c
  807. /*
  808.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  809.  *
  810.  * Code Contributions By : Tim Thompson           twitch!tjt
  811.  *                         Tony Andrews           onecom!wldrdg!tony 
  812.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  813.  */
  814.  
  815. #include "stevie.h"
  816.  
  817. extern char    *Version;
  818.  
  819. static int      helprow;
  820.  
  821. #ifdef    HELP
  822.  
  823. #ifdef    MEGAMAX
  824. overlay "help"
  825. #endif
  826.  
  827. static void     longline();
  828.  
  829. bool_t
  830. help()
  831. {
  832.     outstr(T_ED);
  833.     windgoto(helprow = 0, 0);
  834.  
  835.     longline("\
  836.    Positioning within file\n\
  837.    =======================\n\
  838.       ^F             Forward screenfull             Worked on by:\n\
  839.       ^B             Backward screenfull                Tim Thompson\n");
  840.     longline("\
  841.       ^D             scroll down half screen            Tony Andrews\n\
  842.       ^U             scroll up half screen              G.R. (Fred) Walter\n");
  843.     longline("\
  844.       G              Goto line (end default)\n\
  845.       ]]             next function\n\
  846.       [[             previous function\n\
  847.       /re            next occurence of regular expression 're'\n");
  848.     longline("\
  849.       ?re            prior occurence of regular expression 're'\n\
  850.       n              repeat last / or ?\n\
  851.       N              reverse last / or ?\n\
  852.       %              find matching (, ), {, }, [, or ]\n");
  853.     longline("\
  854. \n\
  855.    Adjusting the screen\n\
  856.    ====================\n\
  857.       ^L             Redraw the screen\n\
  858.       ^E             scroll window down 1 line\n\
  859.       ^Y             scroll window up 1 line\n");
  860.     longline("\
  861.       z<RETURN>      redraw, current line at top\n\
  862.       z-             ... at bottom\n\
  863.       z.             ... at center\n");
  864.  
  865.     windgoto(0, 32);
  866.     longline(Version);
  867. #ifdef AMIGA
  868.     longline(" ");
  869.     longline(__DATE__);
  870.     longline(" ");
  871.     longline(__TIME__);
  872. #endif
  873.  
  874.     windgoto(helprow = Rows - 2, 47);
  875.     longline("<Press space bar to continue>\n");
  876.     windgoto(helprow = Rows - 1, 47);
  877.     longline("<Any other key will quit>");
  878.  
  879.     if (vgetc() != ' ')
  880.     return TRUE;
  881.  
  882.     outstr(T_ED);
  883.     windgoto(helprow = 0, 0);
  884.  
  885.     longline("\
  886.    Character Positioning\n\
  887.    =====================\n\
  888.       ^              first non-white\n\
  889.       0              beginning of line\n\
  890.       $              end of line\n\
  891.       h              backward\n");
  892.     longline("\
  893.       l              forward\n\
  894.       ^H             same as h\n\
  895.       space          same as l\n\
  896.       fx             find 'x' forward\n");
  897.     longline("\
  898.       Fx             find 'x' backward\n\
  899.       tx             upto 'x' forward\n\
  900.       Tx             upto 'x' backward\n\
  901.       ;              Repeat last f, F, t, or T\n");
  902.     longline("\
  903.       ,              inverse of ;\n\
  904.       |              to specified column\n\
  905.       %              find matching (, ), {, }, [, or ]\n");
  906.  
  907.     windgoto(helprow = Rows - 2, 47);
  908.     longline("<Press space bar to continue>\n");
  909.     windgoto(helprow = Rows - 1, 47);
  910.     longline("<Any other key will quit>");
  911.  
  912.     if (vgetc() != ' ')
  913.     return TRUE;
  914.  
  915.     outstr(T_ED);
  916.     windgoto(helprow = 0, 0);
  917.  
  918.     longline("\
  919.     Line Positioning\n\
  920.     =====================\n\
  921.     H           home window line\n\
  922.     L           last window line\n\
  923.     M           middle window line\n");
  924.     longline("\
  925.     +           next line, at first non-white\n\
  926.     -           previous line, at first non-white\n\
  927.     CR          return, same as +\n\
  928.     j           next line, same column\n\
  929.     k           previous line, same column\n");
  930.  
  931.     longline("\
  932. \n\
  933.     Marking and Returning\n\
  934.     =====================\n\
  935.     ``          previous context\n\
  936.     ''          ... at first non-white in line\n");
  937.     longline("\
  938.     mx          mark position with letter 'x'\n\
  939.     `x          to mark 'x'\n\
  940.     'x          ... at first non-white in line\n");
  941.  
  942.     windgoto(helprow = Rows - 2, 47);
  943.     longline("<Press space bar to continue>\n");
  944.     windgoto(helprow = Rows - 1, 47);
  945.     longline("<Any other key will quit>");
  946.  
  947.     if (vgetc() != ' ')
  948.     return TRUE;
  949.  
  950.     outstr(T_ED);
  951.     windgoto(helprow = 0, 0);
  952.  
  953.     longline("\
  954.     Insert and Replace\n\
  955.     ==================\n\
  956.     a           append after cursor\n\
  957.     i           insert before cursor\n\
  958.     A           append at end of line\n\
  959.     I           insert before first non-blank\n");
  960.     longline("\
  961.     o           open line below\n\
  962.     O           open line above\n\
  963.     rx          replace single char with 'x'\n\
  964.     R           replace characters (not yet)\n\
  965.     ~           replace character under cursor with other case\n");
  966.  
  967.     longline("\
  968. \n\
  969.     Words, sentences, paragraphs\n\
  970.     ============================\n\
  971.     w           word forward\n\
  972.     b           back word\n\
  973.     e           end of word\n\
  974.     )           to next sentence (not yet)\n\
  975.     }           to next paragraph (not yet)\n");
  976.     longline("\
  977.     (           back sentence (not yet)\n\
  978.     {           back paragraph (not yet)\n\
  979.     W           blank delimited word\n\
  980.     B           back W\n\
  981.     E           to end of W");
  982.  
  983.     windgoto(helprow = Rows - 2, 47);
  984.     longline("<Press space bar to continue>\n");
  985.     windgoto(helprow = Rows - 1, 47);
  986.     longline("<Any other key will quit>");
  987.  
  988.     if (vgetc() != ' ')
  989.     return TRUE;
  990.  
  991.     outstr(T_ED);
  992.     windgoto(helprow = 0, 0);
  993.  
  994.     longline("\
  995.     Undo  &  Redo\n\
  996.     =============\n\
  997.     u           undo last change\n\
  998.     U           restore current line (not yet)\n\
  999.     .           repeat last change\n");
  1000.  
  1001.     longline("\
  1002. \n\
  1003.     File manipulation\n\
  1004.     =================\n");
  1005.     longline("\
  1006.     :w          write back changes\n\
  1007.     :wq         write and quit\n\
  1008.     :x          write if modified, and quit\n\
  1009.     :q          quit\n\
  1010.     :q!         quit, discard changes\n\
  1011.     :e name     edit file 'name'\n");
  1012.     longline("\
  1013.     :e!         reedit, discard changes\n\
  1014.     :e #        edit alternate file\n\
  1015.     :w name     write file 'name'\n");
  1016.     longline("\
  1017.     :n          edit next file in arglist\n\
  1018.     :n args     specify new arglist (not yet)\n\
  1019.     :rew        rewind arglist\n\
  1020.     :f          show current file and lines\n");
  1021.     longline("\
  1022.     :f file     change current file name\n\
  1023.     :ta tag     to tag file entry 'tag'\n\
  1024.     ^]          :ta, current word is tag");
  1025.  
  1026.     windgoto(helprow = Rows - 2, 47);
  1027.     longline("<Press space bar to continue>\n");
  1028.     windgoto(helprow = Rows - 1, 47);
  1029.     longline("<Any other key will quit>");
  1030.  
  1031.     if (vgetc() != ' ')
  1032.     return TRUE;
  1033.  
  1034.     outstr(T_ED);
  1035.     windgoto(helprow = 0, 0);
  1036.  
  1037.     longline("\
  1038.     Operators (double to affect lines)\n\
  1039.     ==================================\n\
  1040.     d           delete\n\
  1041.     c           change\n");
  1042.     longline("\
  1043.     <           left shift\n\
  1044.     >           right shift\n\
  1045.     y           yank to buffer\n");
  1046.  
  1047.     longline("\n\
  1048.     Yank and Put\n\
  1049.     ============\n\
  1050.     p           put back text\n\
  1051.     P           put before\n\
  1052.     Y           yank lines");
  1053.  
  1054.     windgoto(helprow = Rows - 2, 47);
  1055.     longline("<Press space bar to continue>\n");
  1056.     windgoto(helprow = Rows - 1, 47);
  1057.     longline("<Any other key will quit>");
  1058.  
  1059.     if (vgetc() != ' ')
  1060.     return TRUE;
  1061.  
  1062.     outstr(T_ED);
  1063.     windgoto(helprow = 0, 0);
  1064.  
  1065.     longline("\n\
  1066.     Miscellaneous operations\n\
  1067.     ========================\n\
  1068.     C           change rest of line\n\
  1069.     D           delete rest of line\n\
  1070.     s           substitute chars\n");
  1071.     longline("\
  1072.     S           substitute lines (not yet)\n\
  1073.     J           join lines\n\
  1074.     x           delete characters\n\
  1075.     X           ... before cursor\n\
  1076.     :[range]s/search/replace/[g]\n\
  1077.     :[range]g/search[/p|/d]\n\
  1078.     :[range]d   delete range of lines\n");
  1079.  
  1080.     windgoto(helprow = Rows - 1, 47);
  1081.     longline("<Press any key>");
  1082.  
  1083.     vgetc();
  1084.  
  1085.     return TRUE;
  1086. }
  1087.  
  1088. static void
  1089. longline(p)
  1090.     char           *p;
  1091. {
  1092. # ifdef AMIGA
  1093.     outstr(p);
  1094. # else
  1095.     char           *s;
  1096.  
  1097.     for (s = p; *s; s++) {
  1098.     if (*s == '\n')
  1099.         windgoto(++helprow, 0);
  1100.     else
  1101.         outchar(*s);
  1102.     }
  1103. # endif
  1104. }
  1105. #else
  1106.  
  1107. bool_t
  1108. help()
  1109. {
  1110.     msg("Sorry, help not configured");
  1111.     return FALSE;
  1112. }
  1113. #endif
  1114. SHAR_EOF
  1115. cat << \SHAR_EOF > main.c
  1116. /*
  1117.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1118.  *
  1119.  * Code Contributions By : Tim Thompson           twitch!tjt
  1120.  *                         Tony Andrews           onecom!wldrdg!tony 
  1121.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1122.  */
  1123.  
  1124. #include "stevie.h"
  1125.  
  1126. int             Rows;        /* Number of Rows and Columns */
  1127. int             Columns;    /* in the current window. */
  1128.  
  1129. char           *Realscreen = NULL;    /* What's currently on the screen, a
  1130.                      * single array of size Rows*Columns. */
  1131. char           *Nextscreen = NULL;    /* What's to be put on the screen. */
  1132. int             NumLineSizes = 0;    /* # of active LineSizes */
  1133. LINE          **LinePointers = NULL;    /* Pointer to the line for LineSizes */
  1134. char           *LineSizes = NULL;    /* Size of a line (pline output) */
  1135.  
  1136. char           *Filename = NULL;/* Current file name */
  1137.  
  1138. LPtr           *Filemem;    /* The contents of the file, as a single
  1139.                  * array. */
  1140. LPtr           *Filetop;    /* Line 'above' the start of the file */
  1141.  
  1142. LPtr           *Fileend;    /* Pointer to the end of the file in Filemem.
  1143.                  * (It points to the byte AFTER the last
  1144.                  * byte.) */
  1145.  
  1146. LPtr           *Topchar;    /* Pointer to the byte in Filemem which is in
  1147.                  * the upper left corner of the screen. */
  1148.  
  1149. LPtr           *Botchar;    /* Pointer to the byte in Filemem which is
  1150.                  * just off the bottom of the screen. */
  1151.  
  1152. LPtr           *Curschar;    /* Pointer to byte in Filemem at which the
  1153.                  * cursor is currently placed. */
  1154.  
  1155. int             Curscol;    /* Current position of cursor (column) */
  1156. int             Cursrow;    /* Current position of cursor (row) */
  1157.  
  1158. int             Cursvcol;    /* Current virtual column, the column number
  1159.                  * of the file's actual line, as opposed to
  1160.                  * the column number we're at on the screen.
  1161.                  * This makes a difference on lines that span
  1162.                  * more than one screen line. */
  1163.  
  1164. int             Curswant = 0;    /* The column we'd like to be at. This is
  1165.                  * used try to stay in the same column
  1166.                  * through up/down cursor motions. */
  1167.  
  1168. bool_t          set_want_col;    /* If set, then update Curswant the next time
  1169.                  * through cursupdate() to the current
  1170.                  * virtual column. */
  1171.  
  1172. int             State = NORMAL;    /* This is the current state of the command
  1173.                  * interpreter. */
  1174.  
  1175. int             Prenum = 0;    /* The (optional) number before a command. */
  1176.  
  1177. LPtr           *Insstart;    /* This is where the latest insert/append
  1178.                  * mode started. */
  1179.  
  1180. bool_t          Changed = FALSE;/* Set to TRUE if something in the file has
  1181.                  * been changed and not written out. */
  1182.  
  1183. char           *IObuff;        /* file reads are done, one line at a time,
  1184.                  * into this buffer; as well as sprintf's */
  1185.  
  1186. char           *Insbuffptr = NULL;
  1187. char           *Insbuff;    /* Each insertion gets stuffed into this
  1188.                  * buffer. */
  1189.  
  1190. char           *Readbuffptr = NULL;
  1191. char           *Readbuff;    /* Having this buffer allows STEVIE to easily
  1192.                  * make itself do commands */
  1193.  
  1194. char           *Redobuffptr = NULL;
  1195. char           *Redobuff;    /* Each command should stuff characters into
  1196.                  * this buffer that will re-execute itself. */
  1197.  
  1198. bool_t          UndoInProgress = FALSE;    /* Set to TRUE if undo'ing */
  1199. char           *Undobuffptr = NULL;
  1200. char           *Undobuff;    /* Each command should stuff characters into
  1201.                  * this buffer that will undo its effects. */
  1202.  
  1203. char           *UndoUndobuffptr = NULL;
  1204. char           *UndoUndobuff;    /* Each command should stuff characters into
  1205.                  * this buffer that will undo its undo. */
  1206.  
  1207. char           *Yankbuffptr = NULL;
  1208. char           *Yankbuff;    /* Yank buffer */
  1209.  
  1210. char            last_command = NUL;    /* last command */
  1211. char            last_command_char = NUL;    /* character needed to undo
  1212.                          * last command */
  1213.  
  1214. bool_t          RedrawingDisabled = FALSE;    /* Set to TRUE if undo'ing or
  1215.                          * put'ing */
  1216.  
  1217. bool_t          MustRedrawLine = FALSE;    /* Set to TRUE if we must redraw the
  1218.                      * current line */
  1219. bool_t          MustRedrawScreen = TRUE;    /* Set to TRUE if we must
  1220.                          * redraw the screen */
  1221.  
  1222. char          **files;        /* list of input files */
  1223. int             numfiles;    /* number of input files */
  1224. int             curfile;    /* number of the current file */
  1225.  
  1226. static void
  1227. usage()
  1228. {
  1229.     fprintf(stderr, "usage: stevie [file ...]\n");
  1230.     fprintf(stderr, "       stevie -t tag\n");
  1231.     fprintf(stderr, "       stevie +[num] file\n");
  1232.     fprintf(stderr, "       stevie +/pat  file\n");
  1233.     exit(1);
  1234. }
  1235.  
  1236. #ifdef AMIGA
  1237. void
  1238. #else
  1239. int
  1240. #endif
  1241. main(argc, argv)
  1242.     int             argc;
  1243.     char          **argv;
  1244. {
  1245.     char           *initstr, *getenv();    /* init string from the environment */
  1246.     char           *tag = NULL;    /* tag from command line */
  1247.     char           *pat = NULL;    /* pattern from command line */
  1248.     int             line = -1;    /* line number from command line */
  1249.  
  1250.     int             atoi();
  1251.  
  1252. #ifdef AMIGA
  1253. /*
  1254.  * This won't be needed if you have a version of Lattice 4.01 without broken
  1255.  * break signal handling.
  1256.  */
  1257.     (void) signal(SIGINT, SIG_IGN);
  1258. #endif
  1259.  
  1260.     /*
  1261.      * Process the command line arguments. 
  1262.      */
  1263.     if (argc > 1) {
  1264.     switch (argv[1][0]) {
  1265.  
  1266.       case '-':        /* -t tag */
  1267.         if (argv[1][1] != 't')
  1268.         usage();
  1269.  
  1270.         if (argv[2] == NULL)
  1271.         usage();
  1272.  
  1273.         Filename = NULL;
  1274.         tag = argv[2];
  1275.         numfiles = 1;
  1276.         break;
  1277.  
  1278.       case '+':        /* +n or +/pat */
  1279.         if (argv[1][1] == '/') {
  1280.         if (argv[2] == NULL)
  1281.             usage();
  1282.         Filename = strsave(argv[2]);
  1283.         pat = &(argv[1][1]);
  1284.         numfiles = 1;
  1285.  
  1286.         } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
  1287.         if (argv[2] == NULL)
  1288.             usage();
  1289.         Filename = strsave(argv[2]);
  1290.         numfiles = 1;
  1291.  
  1292.         line = (isdigit(argv[1][1])) ?
  1293.             atoi(&(argv[1][1])) : 0;
  1294.         } else
  1295.         usage();
  1296.  
  1297.         break;
  1298.  
  1299.       default:        /* must be a file name */
  1300.         Filename = strsave(argv[1]);
  1301.         files = &(argv[1]);
  1302.         numfiles = argc - 1;
  1303.         break;
  1304.     }
  1305.     } else {
  1306.     Filename = NULL;
  1307.     numfiles = 1;
  1308.     }
  1309.     curfile = 0;
  1310.  
  1311.     windinit();
  1312.  
  1313.     /*
  1314.      * Allocate LPtr structures for all the various position pointers 
  1315.      */
  1316.     if ((Filemem = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1317.     fprintf(stderr, "Can't allocate data structures\n");
  1318.     windexit(0);
  1319.     }
  1320.     if ((Filetop = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1321.     fprintf(stderr, "Can't allocate data structures\n");
  1322.     windexit(0);
  1323.     }
  1324.     if ((Fileend = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1325.     fprintf(stderr, "Can't allocate data structures\n");
  1326.     windexit(0);
  1327.     }
  1328.     if ((Topchar = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1329.     fprintf(stderr, "Can't allocate data structures\n");
  1330.     windexit(0);
  1331.     }
  1332.     if ((Botchar = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1333.     fprintf(stderr, "Can't allocate data structures\n");
  1334.     windexit(0);
  1335.     }
  1336.     if ((Curschar = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1337.     fprintf(stderr, "Can't allocate data structures\n");
  1338.     windexit(0);
  1339.     }
  1340.     if ((Insstart = (LPtr *) alloc((unsigned) sizeof(LPtr))) == NULL) {
  1341.     fprintf(stderr, "Can't allocate data structures\n");
  1342.     windexit(0);
  1343.     }
  1344.     /*
  1345.      * Allocate space for the many buffers 
  1346.      */
  1347.     if ((IObuff = alloc(IOSIZE)) == NULL) {
  1348.     fprintf(stderr, "Can't allocate data structures\n");
  1349.     windexit(0);
  1350.     }
  1351.     if ((Insbuff = alloc(INSERT_SIZE)) == NULL) {
  1352.     fprintf(stderr, "Can't allocate data structures\n");
  1353.     windexit(0);
  1354.     }
  1355.     if ((Readbuff = alloc(READSIZE)) == NULL) {
  1356.     fprintf(stderr, "Can't allocate data structures\n");
  1357.     windexit(0);
  1358.     }
  1359.     if ((Redobuff = alloc(REDO_UNDO_SIZE)) == NULL) {
  1360.     fprintf(stderr, "Can't allocate data structures\n");
  1361.     windexit(0);
  1362.     }
  1363.     if ((Undobuff = alloc(REDO_UNDO_SIZE)) == NULL) {
  1364.     fprintf(stderr, "Can't allocate data structures\n");
  1365.     windexit(0);
  1366.     }
  1367.     if ((UndoUndobuff = alloc(REDO_UNDO_SIZE)) == NULL) {
  1368.     fprintf(stderr, "Can't allocate data structures\n");
  1369.     windexit(0);
  1370.     }
  1371.     if ((Yankbuff = alloc(YANKSIZE)) == NULL) {
  1372.     fprintf(stderr, "Can't allocate data structures\n");
  1373.     windexit(0);
  1374.     }
  1375.     screenalloc();
  1376.     filealloc();        /* Initialize Filemem, Filetop & Fileend */
  1377.  
  1378.     screenclear();
  1379.  
  1380.     if ((initstr = getenv("EXINIT")) != NULL) {
  1381.     char           *lp, buf[128];
  1382.  
  1383.     if ((lp = getenv("LINES")) != NULL) {
  1384.         sprintf(buf, "%s lines=%s", initstr, lp);
  1385.         readcmdline(':', buf);
  1386.     } else
  1387.         readcmdline(':', initstr);
  1388.     }
  1389.     if (Filename != NULL) {
  1390.     if (readfile(Filename, Filemem, FALSE))
  1391.         filemess("[New File]");
  1392.     } else
  1393.     msg("Empty Buffer");
  1394.  
  1395.     setpcmark();
  1396.  
  1397.     updateNextscreen(NOT_VALID);
  1398.  
  1399.     if (tag) {
  1400.     stuffReadbuff(":ta ");
  1401.     stuffReadbuff(tag);
  1402.     stuffReadbuff("\n");
  1403.  
  1404.     } else if (pat) {
  1405.     stuffReadbuff(pat);
  1406.     stuffReadbuff("\n");
  1407.  
  1408.     } else if (line >= 0) {
  1409.     if (line > 0)
  1410.         stuffnumReadbuff(line);
  1411.     stuffReadbuff("G");
  1412.     }
  1413.     edit();
  1414.  
  1415.     windexit(0);
  1416. }
  1417.  
  1418. void
  1419. stuffReadbuff(s)
  1420.     char           *s;
  1421. {
  1422.     if (strlen(s) == 0)
  1423.     return;
  1424.  
  1425.     if (Readbuffptr == NULL) {
  1426.     if ((strlen(s) + 1) < READSIZE) {
  1427.         strcpy(Readbuff, s);
  1428.         Readbuffptr = Readbuff;
  1429.         return;
  1430.     }
  1431.     } else if ((strlen(Readbuff) + (strlen(s) + 1)) < READSIZE) {
  1432.     strcat(Readbuff, s);
  1433.     return;
  1434.     }
  1435.     emsg("Couldn't stuffReadbuff() - clearing Readbuff\n");
  1436.     *Readbuff = NUL;
  1437.     Readbuffptr = NULL;
  1438. }
  1439.  
  1440. void
  1441. stuffnumReadbuff(n)
  1442.     int             n;
  1443. {
  1444.     char            buf[32];
  1445.  
  1446.     sprintf(buf, "%d", n);
  1447.     stuffReadbuff(buf);
  1448. }
  1449.  
  1450. /* OPTRESULT */
  1451. char
  1452. vgetc()
  1453. {
  1454.     int             c;
  1455.  
  1456.     /*
  1457.      * inchar() may map special keys by using stuffReadbuff(). If it does so,
  1458.      * it returns -1 so we know to loop here to get a real char. 
  1459.      */
  1460.     do {
  1461.     if (Readbuffptr != NULL) {
  1462.         char            nextc = *Readbuffptr++;
  1463.  
  1464.         if (*Readbuffptr == NUL) {
  1465.         *Readbuff = NUL;
  1466.         Readbuffptr = NULL;
  1467.         }
  1468.         return (nextc);
  1469.     }
  1470.     c = inchar();
  1471.     } while (c == -1);
  1472.  
  1473.     return (char) c;
  1474. }
  1475.  
  1476. char
  1477. vpeekc()
  1478. {
  1479.     if (Readbuffptr != NULL)
  1480.     return (*Readbuffptr);
  1481.     return (NUL);
  1482. }
  1483. SHAR_EOF
  1484. cat << \SHAR_EOF > misccmds.c
  1485. /*
  1486.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1487.  *
  1488.  * Code Contributions By : Tim Thompson           twitch!tjt
  1489.  *                         Tony Andrews           onecom!wldrdg!tony 
  1490.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1491.  */
  1492.  
  1493. #include "stevie.h"
  1494.  
  1495. extern int      did_ai;
  1496.  
  1497. /*
  1498.  * OpenForward 
  1499.  *
  1500.  * Add a blank line below the current line. 
  1501.  */
  1502.  
  1503. bool_t
  1504. OpenForward(can_ai)
  1505.     int             can_ai;
  1506. {
  1507.     LINE           *l;
  1508.     LPtr           *next;
  1509.     char           *s;        /* string to be moved to new line, if any */
  1510.     int             newindex = 0;    /* index of the cursor on the new
  1511.                      * line */
  1512.  
  1513.     /*
  1514.      * If we're in insert mode, we need to move the remainder of the current
  1515.      * line onto the new line. Otherwise the new line is left blank. 
  1516.      */
  1517.     if (State == INSERT)
  1518.     s = &Curschar->linep->s[Curschar->index];
  1519.     else
  1520.     s = "";
  1521.  
  1522.     if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  1523.     next = Fileend;
  1524.  
  1525.     /*
  1526.      * By asking for as much space as the prior line had we make sure that
  1527.      * we'll have enough space for any auto-indenting. 
  1528.      */
  1529.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
  1530.     emsg("out of memory");
  1531.     beep();
  1532.     sleep(2);
  1533.     return (FALSE);
  1534.     }
  1535.     if (can_ai && P(P_AI)) {
  1536.     char           *p;
  1537.  
  1538.     /*
  1539.      * Copy prior line, and truncate after white space 
  1540.      */
  1541.     strcpy(l->s, Curschar->linep->s);
  1542.  
  1543.     for (p = l->s; *p == ' ' || *p == TAB; p++);
  1544.     *p = NUL;
  1545.     newindex = p - l->s;
  1546.     AppendToInsbuff(l->s);
  1547.     if (*s != NUL)
  1548.         strcat(l->s, s);
  1549.  
  1550.     /*
  1551.      * If we just did an auto-indent, then we didn't type anything on the
  1552.      * prior line, and it should be truncated. 
  1553.      */
  1554.     if (did_ai)
  1555.         Curschar->linep->s[0] = NUL;
  1556.  
  1557.     did_ai = TRUE;
  1558.     } else if (*s != NUL) {
  1559.     strcpy(l->s, s);    /* copy string to new line */
  1560.     }
  1561.     if (State == INSERT)    /* truncate current line at cursor */
  1562.     *s = NUL;
  1563.  
  1564.     Curschar->linep->next = l;    /* link neighbors to new line */
  1565.     next->linep->prev = l;
  1566.  
  1567.     l->prev = Curschar->linep;    /* link new line to neighbors */
  1568.     l->next = next->linep;
  1569.  
  1570.     if (next == Fileend) {    /* new line at end */
  1571.     l->num = Curschar->linep->num + LINEINC;
  1572.     } else if ((l->prev->num) + 1 == l->next->num) {    /* no gap, renumber */
  1573.     renum();
  1574.     } else {            /* stick it in the middle */
  1575.     long            lnum;
  1576.  
  1577.     lnum = (l->prev->num + l->next->num) / 2;
  1578.     l->num = lnum;
  1579.     }
  1580.  
  1581.     if (!RedrawingDisabled) {
  1582.     /*
  1583.      * Get the cursor to the start of the line, so that 'Cursrow' gets
  1584.      * set to the right physical line number for the stuff that
  1585.      * follows... 
  1586.      */
  1587.     Curschar->index = 0;
  1588.     cursupdate();
  1589.  
  1590.     /*
  1591.      * If we're doing an open on the last logical line, then go ahead and
  1592.      * scroll the screen up. Otherwise, just insert a blank line at the
  1593.      * right place. We use calls to plines() in case the cursor is
  1594.      * resting on a long line. 
  1595.      */
  1596.     if (Cursrow + plines(Curschar) == (Rows - 1))
  1597.         scrollup(1);
  1598.     else
  1599.         s_ins(Cursrow + plines(Curschar), 1, Rows, Columns);
  1600.     }
  1601.     *Curschar = *nextline(Curschar);    /* cursor moves down */
  1602.     Curschar->index = newindex;
  1603.  
  1604.     if (!RedrawingDisabled) {
  1605.     /* because Botchar is now invalid */
  1606.     updateNextscreen(VALID_TO_CURSCHAR);
  1607.     cursupdate();        /* update Cursrow before insert */
  1608.     }
  1609.     CHANGED;
  1610.  
  1611.     return (TRUE);
  1612. }
  1613.  
  1614. /*
  1615.  * OpenBackward 
  1616.  *
  1617.  * Add a blank line above the current line. 
  1618.  */
  1619.  
  1620. bool_t
  1621. OpenBackward(can_ai)
  1622.     int             can_ai;
  1623. {
  1624.     LINE           *l;
  1625.     LINE           *prev;
  1626.     int             newindex = 0;    /* index of the cursor on the new
  1627.                      * line */
  1628.  
  1629.     prev = Curschar->linep->prev;
  1630.  
  1631.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
  1632.     emsg("out of memory");
  1633.     beep();
  1634.     sleep(2);
  1635.     return (FALSE);
  1636.     }
  1637.     Curschar->linep->prev = l;    /* link neighbors to new line */
  1638.     prev->next = l;
  1639.  
  1640.     l->next = Curschar->linep;    /* link new line to neighbors */
  1641.     l->prev = prev;
  1642.  
  1643.     if (can_ai && P(P_AI)) {
  1644.     char           *p;
  1645.  
  1646.     /*
  1647.      * Copy current line, and truncate after white space 
  1648.      */
  1649.     strcpy(l->s, Curschar->linep->s);
  1650.  
  1651.     for (p = l->s; *p == ' ' || *p == TAB; p++);
  1652.     *p = NUL;
  1653.     newindex = p - l->s;
  1654.     AppendToInsbuff(l->s);
  1655.  
  1656.     did_ai = TRUE;
  1657.     }
  1658.     Curschar->linep = Curschar->linep->prev;
  1659.     Curschar->index = newindex;
  1660.  
  1661.     if (prev == Filetop->linep) {    /* new start of file */
  1662.     Filemem->linep = l;
  1663.     renum();
  1664.     } else if ((l->prev->num) + 1 == l->next->num) {    /* no gap, renumber */
  1665.     renum();
  1666.     } else {            /* stick it in the middle */
  1667.     long            lnum;
  1668.  
  1669.     lnum = (l->prev->num + l->next->num) / 2;
  1670.     l->num = lnum;
  1671.     }
  1672.  
  1673.     if (!RedrawingDisabled) {
  1674.     if (LINEOF(Curschar) < LINEOF(Topchar)) {
  1675.         Topchar->linep = Curschar->linep;
  1676.         updateNextscreen(NOT_VALID);
  1677.     } else {
  1678.         updateNextscreen(VALID_TO_CURSCHAR);
  1679.     }
  1680.     cursupdate();        /* update Cursrow before insert */
  1681.     if (Cursrow != 0)
  1682.         s_ins(Cursrow, 1, Rows, Columns);    /* insert a physical line */
  1683.     }
  1684.     CHANGED;
  1685.  
  1686.     return (TRUE);
  1687. }
  1688.  
  1689. int
  1690. cntllines(pbegin, pend)
  1691.     LPtr           *pbegin, *pend;
  1692. {
  1693.     register LINE  *lp;
  1694.     register int    lnum = 1;
  1695.  
  1696.     for (lp = pbegin->linep; lp != pend->linep; lp = lp->next)
  1697.     lnum++;
  1698.  
  1699.     return (lnum);
  1700. }
  1701.  
  1702. /*
  1703.  * plines(p) - return the number of physical screen lines taken by line 'p' 
  1704.  */
  1705. int
  1706. plines(p)
  1707.     LPtr           *p;
  1708. {
  1709.     register int    col = 0;
  1710.     register char  *s;
  1711.  
  1712.     if (p == NULL) {
  1713.     fprintf(stderr, "plines(p) : p == NULL ????");
  1714.     return (0);
  1715.     }
  1716.     s = p->linep->s;
  1717.  
  1718.     if (*s == NUL)        /* empty line */
  1719.     return 1;
  1720.  
  1721.     for (; *s != NUL; s++) {
  1722.     if (*s == TAB && !P(P_LS))
  1723.         col += P(P_TS) - (col % P(P_TS));
  1724.     else
  1725.         col += chars[(unsigned) (*s & 0xff)].ch_size;
  1726.     }
  1727.  
  1728.     /*
  1729.      * If list mode is on, then the '$' at the end of the line takes up one
  1730.      * extra column. 
  1731.      */
  1732.     if (P(P_LS))
  1733.     col += 1;
  1734.  
  1735.     /*
  1736.      * If 'number' mode is on, add another 8. 
  1737.      */
  1738.     if (P(P_NU))
  1739.     col += 8;
  1740.  
  1741.     return ((col + (Columns - 1)) / Columns);
  1742. }
  1743.  
  1744. void
  1745. fileinfo()
  1746. {
  1747.     long            l1, l2;
  1748.     char            buf[MAX_COLUMNS + 1];
  1749.  
  1750.     if (bufempty()) {
  1751.     msg("Buffer Empty");
  1752.     return;
  1753.     }
  1754.     l1 = cntllines(Filemem, Curschar);
  1755.     l2 = cntllines(Filemem, Fileend) - 1;
  1756.     sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
  1757.         (Filename != NULL) ? Filename : "No File",
  1758.         Changed ? " [Modified]" : "",
  1759.         l1, l2, (l1 * 100) / l2);
  1760.     msg(buf);
  1761. }
  1762.  
  1763. /*
  1764.  * gotoline(n) - return a pointer to line 'n' 
  1765.  *
  1766.  * Returns a pointer to the last line of the file if n is zero, or beyond the
  1767.  * end of the file. 
  1768.  */
  1769. LPtr           *
  1770. gotoline(n)
  1771.     int             n;
  1772. {
  1773.     static LPtr     l;
  1774.  
  1775.     l.index = 0;
  1776.  
  1777.     if (n == 0)
  1778.     l = *prevline(Fileend);
  1779.     else {
  1780.     LPtr           *p;
  1781.  
  1782.     for (l = *Filemem; --n > 0; l = *p)
  1783.         if ((p = nextline(&l)) == NULL)
  1784.         break;
  1785.     }
  1786.     return &l;
  1787. }
  1788.  
  1789. void
  1790. inschar(c)
  1791.     char            c;
  1792. {
  1793.     register char  *p;
  1794.     register char  *pend;
  1795.  
  1796.     /* make room for the new char. */
  1797.     if (!canincrease(1))
  1798.     return;
  1799.  
  1800.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  1801.     pend = &Curschar->linep->s[Curschar->index];
  1802.  
  1803.     for (; p > pend; p--)
  1804.     *p = *(p - 1);
  1805.  
  1806.     *p = c;
  1807.  
  1808.     if (RedrawingDisabled) {
  1809.     Curschar->index++;
  1810.     return;
  1811.     }
  1812.     /*
  1813.      * If we're in insert mode and showmatch mode is set, then check for
  1814.      * right parens and braces. If there isn't a match, then beep. If there
  1815.      * is a match AND it's on the screen, then flash to it briefly. If it
  1816.      * isn't on the screen, don't do anything. 
  1817.      */
  1818.     if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  1819.     LPtr           *lpos, csave;
  1820.  
  1821.     if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  1822.         beep();
  1823.     else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  1824.         updateNextscreen(VALID_TO_CURSCHAR);    /* show the new char
  1825.                              * first */
  1826.         updateRealscreen();
  1827.         csave = *Curschar;
  1828.         *Curschar = *lpos;    /* move to matching char */
  1829.         cursupdate();
  1830.         windgoto(Cursrow, Curscol);
  1831.         delay();        /* brief pause */
  1832.         *Curschar = csave;    /* restore cursor position */
  1833.         cursupdate();
  1834.     }
  1835.     }
  1836.     inc(Curschar);
  1837.  
  1838.     CHANGED;
  1839. }
  1840.  
  1841. void
  1842. insstr(s)
  1843.     register char  *s;
  1844. {
  1845.     register char  *p;
  1846.     register char  *pend;
  1847.     register int    n = strlen(s);
  1848.  
  1849.     /* Move everything in the file over to make */
  1850.     /* room for the new string. */
  1851.     if (!canincrease(n))
  1852.     return;
  1853.  
  1854.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + n];
  1855.     pend = &Curschar->linep->s[Curschar->index];
  1856.  
  1857.     for (; p > pend; p--)
  1858.     *p = *(p - n);
  1859.  
  1860.     for (; n > 0; n--) {
  1861.     *p++ = *s++;
  1862.     Curschar->index++;
  1863.     }
  1864.     CHANGED;
  1865. }
  1866.  
  1867. bool_t
  1868. delchar(fixpos, undo)
  1869.     bool_t          fixpos;    /* if TRUE fix the cursor position when done */
  1870.     bool_t          undo;    /* if TRUE put char deleted into Undo buffer */
  1871. {
  1872.     int             i;
  1873.  
  1874.     /* Check for degenerate case; there's nothing in the file. */
  1875.     if (bufempty())
  1876.     return FALSE;
  1877.  
  1878.     if (lineempty(Curschar))    /* can't do anything */
  1879.     return FALSE;
  1880.  
  1881.     if (undo)
  1882.     AppendToUndobuff(mkstr(gchar(Curschar)));
  1883.  
  1884.     /* Delete the char. at Curschar by shifting everything in the line down. */
  1885.     for (i = Curschar->index + 1; i < Curschar->linep->size; i++)
  1886.     Curschar->linep->s[i - 1] = Curschar->linep->s[i];
  1887.  
  1888.     /*
  1889.      * If we just took off the last character of a non-blank line, we don't
  1890.      * want to end up positioned at the newline. 
  1891.      */
  1892.     if (fixpos) {
  1893.     if (gchar(Curschar) == NUL && Curschar->index > 0 && State != INSERT)
  1894.         Curschar->index--;
  1895.     }
  1896.     CHANGED;
  1897.     return TRUE;
  1898. }
  1899.  
  1900. void
  1901. delline(nlines, can_update)
  1902.     int             nlines;
  1903.     bool_t          can_update;
  1904. {
  1905.     register LINE  *p;
  1906.     register LINE  *q;
  1907.     int             doscreen;    /* if true, update the screen */
  1908.     int             num_plines = 0;
  1909.  
  1910.     doscreen = can_update;
  1911.     /*
  1912.      * There's no point in keeping the screen updated if we're deleting more
  1913.      * than a screen's worth of lines. 
  1914.      */
  1915.     if (nlines > (Rows - 1) && can_update) {
  1916.     doscreen = FALSE;
  1917.     /* flaky way to clear rest of screen */
  1918.     s_del(Cursrow, Rows - 1, Rows, Columns);
  1919.     }
  1920.     while (nlines-- > 0) {
  1921.  
  1922.     if (bufempty())        /* nothing to delete */
  1923.         break;
  1924.  
  1925.     if (buf1line()) {    /* just clear the line */
  1926.         Curschar->linep->s[0] = NUL;
  1927.         Curschar->index = 0;
  1928.         break;
  1929.     }
  1930.     p = Curschar->linep->prev;
  1931.     q = Curschar->linep->next;
  1932.  
  1933.     if (p == Filetop->linep) {    /* first line of file so... */
  1934.         Filemem->linep = q;    /* adjust start of file */
  1935.         Topchar->linep = q;    /* and screen */
  1936.     }
  1937.     p->next = q;
  1938.     q->prev = p;
  1939.  
  1940.     clrmark(Curschar->linep);    /* clear marks for the line */
  1941.  
  1942.     /*
  1943.      * Set up to delete the correct number of physical lines on the
  1944.      * screen 
  1945.      */
  1946.     if (doscreen)
  1947.         num_plines += plines(Curschar);
  1948.  
  1949.     /*
  1950.      * If deleting the top line on the screen, adjust Topchar 
  1951.      */
  1952.     if (Topchar->linep == Curschar->linep)
  1953.         Topchar->linep = q;
  1954.  
  1955.     free(Curschar->linep->s);
  1956.     free((char *) (Curschar->linep));
  1957.  
  1958.     Curschar->linep = q;
  1959.     Curschar->index = 0;    /* is this right? */
  1960.  
  1961.     CHANGED;
  1962.  
  1963.     /* If we delete the last line in the file, back up */
  1964.     if (Curschar->linep == Fileend->linep) {
  1965.         Curschar->linep = Curschar->linep->prev;
  1966.         /* and don't try to delete any more lines */
  1967.         break;
  1968.     }
  1969.     }
  1970.     /*
  1971.      * Delete the correct number of physical lines on the screen 
  1972.      */
  1973.     if (doscreen && num_plines > 0)
  1974.     s_del(Cursrow, num_plines, Rows, Columns);
  1975. }
  1976. SHAR_EOF
  1977. cat << \SHAR_EOF > screen.c
  1978. /*
  1979.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1980.  *
  1981.  * Code Contributions By : Tim Thompson           twitch!tjt
  1982.  *                         Tony Andrews           onecom!wldrdg!tony 
  1983.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1984.  */
  1985.  
  1986. #include "stevie.h"
  1987.  
  1988. /*
  1989.  * The following variable is set (in cursupdate) to the number of physical
  1990.  * lines taken by the line the cursor is on. We use this to avoid extra calls
  1991.  * to plines(). The optimized routines updateline() and redrawline()
  1992.  * make sure that the size of the cursor line hasn't changed. If so, lines below
  1993.  * the cursor will move up or down and we need to call the routines
  1994.  * updateNextscreen() and updateRealscreen() to examine the entire screen. 
  1995.  */
  1996. static int      Cline_size;    /* size (in rows) of the cursor line */
  1997. static int      Cline_row;    /* starting row of the cursor line */
  1998.  
  1999. /*
  2000.  * updateline() - like updateNextscreen() but only for cursor line 
  2001.  *
  2002.  * This determines whether or not we need to call updateNextscreen() to examine
  2003.  * the entire screen for changes. This occurs if the size of the cursor line
  2004.  * (in rows) hasn't changed.
  2005.  */
  2006. void
  2007. updateline()
  2008. {
  2009.     register int    row;
  2010.     register int    col;
  2011.     register char  *screenp;
  2012.     register char   c;
  2013.     LPtr            memp;
  2014.     register char  *nextrow;
  2015.     char            extra[16];
  2016.     char           *p_extra;
  2017.     int             n_extra;
  2018.     int             n;
  2019.     bool_t          eof;
  2020.     int             lno;    /* number of the line we're doing */
  2021.     int             coff;    /* column offset */
  2022.  
  2023.     MustRedrawLine = TRUE;
  2024.  
  2025.     coff = P(P_NU) ? 8 : 0;
  2026.  
  2027.     /*
  2028.      * This should be done more efficiently. 
  2029.      */
  2030.     if (P(P_NU))
  2031.     lno = cntllines(Filemem, Curschar);
  2032.  
  2033.     screenp = Nextscreen + (Cline_row * Columns);
  2034.  
  2035.     memp = *Curschar;
  2036.     memp.index = 0;
  2037.  
  2038.     eof = FALSE;
  2039.     col = 0;
  2040.     row = Cline_row;
  2041.  
  2042.     p_extra = NULL;
  2043.     n_extra = 0;
  2044.     if (P(P_NU)) {
  2045.     strcpy(extra, mkline(lno));
  2046.     p_extra = extra;
  2047.     n_extra = 8;
  2048.     }
  2049.     while (!eof) {
  2050.     /* Get the next character to put on the screen. */
  2051.  
  2052.     /*
  2053.      * The 'extra' array contains the extra stuff that is inserted to
  2054.      * represent special characters (tabs, and other non-printable stuff.
  2055.      * The order in the 'extra' array is reversed. 
  2056.      */
  2057.  
  2058.     if (n_extra > 0) {
  2059.         c = *p_extra++;
  2060.         n_extra--;
  2061.     } else {
  2062.         c = gchar(&memp);
  2063.         if (inc(&memp) == -1)
  2064.         eof = TRUE;
  2065.         /*
  2066.          * when getting a character from the file, we may have to turn it
  2067.          * into something else on the way to putting it into
  2068.          * 'Nextscreen'. 
  2069.          */
  2070.         if (c == TAB && !P(P_LS)) {
  2071.         strcpy(extra, "               ");
  2072.         p_extra = extra;
  2073.         /* tab amount depends on current column */
  2074.         n_extra = ((P(P_TS) - 1) - (col - coff) % P(P_TS));
  2075.         c = ' ';
  2076.         } else if (c == NUL && P(P_LS)) {
  2077.         extra[0] = NUL;
  2078.         p_extra = extra;
  2079.         n_extra = 1;
  2080.         c = '$';
  2081.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  2082.         p_extra = chars[c].ch_str;
  2083.         c = *p_extra++;
  2084.         n_extra = n - 1;
  2085.         }
  2086.     }
  2087.  
  2088.     if (c == NUL) {
  2089.         row++;
  2090.         /* get pointer to start of next row */
  2091.         nextrow = Nextscreen + (row * Columns);
  2092.         /* blank out the rest of this row */
  2093.         while (screenp < nextrow)
  2094.         *screenp++ = ' ';
  2095.         break;
  2096.     }
  2097.     if (col >= Columns) {
  2098.         row++;
  2099.         col = 0;
  2100.     }
  2101.     /* store the character in Nextscreen */
  2102.     *screenp++ = c;
  2103.     col++;
  2104.     }
  2105.     if ((row - Cline_row) != Cline_size) {
  2106.     updateNextscreen(VALID_TO_CURSCHAR);
  2107.     }
  2108. }
  2109.  
  2110. /*
  2111.  * redrawline 
  2112.  *
  2113.  * Like updateRealscreen() but only for the cursor line. 
  2114.  */
  2115. void
  2116. redrawline()
  2117. {
  2118.     register char  *np = Nextscreen + (Cline_row * Columns);
  2119.     register char  *rp = Realscreen + (Cline_row * Columns);
  2120.     register char  *endline;
  2121.     register int    row, col;
  2122.     int             gorow = -1, gocol = -1;
  2123.  
  2124.     if (RedrawingDisabled)
  2125.     return;
  2126.  
  2127.     if (!MustRedrawLine && !MustRedrawScreen)
  2128.     return;
  2129.  
  2130.     if (MustRedrawScreen) {
  2131.     msg("STEVIE internal error: redrawline called");
  2132.     sleep(5);
  2133.     }
  2134.     endline = np + (Cline_size * Columns);
  2135.  
  2136.     row = Cline_row;
  2137.     col = 0;
  2138.  
  2139.     outstr(T_CI);        /* disable cursor */
  2140.  
  2141.     for (; np < endline; np++, rp++) {
  2142.     /* If desired screen (contents of Nextscreen) does not */
  2143.     /* match what's really there, put it there. */
  2144.     if (*np != *rp) {
  2145.         /* if we are positioned at the right place, */
  2146.         /* we don't have to use windgoto(). */
  2147.         if (gocol != col || gorow != row) {
  2148.         /*
  2149.          * If we're just off by one, don't send an entire esc. seq.
  2150.          * (this happens a lot!) 
  2151.          */
  2152.         if (gorow == row && gocol + 1 == col) {
  2153.             outchar(*(np - 1));
  2154.             gocol++;
  2155.         } else
  2156.             windgoto(gorow = row, gocol = col);
  2157.         }
  2158.         outchar(*rp = *np);
  2159.         gocol++;
  2160.     }
  2161.     if (++col >= Columns) {
  2162.         col = 0;
  2163.         row++;
  2164.     }
  2165.     }
  2166.     outstr(T_CV);        /* enable cursor again */
  2167.  
  2168.     MustRedrawScreen = FALSE;
  2169. }
  2170.  
  2171. /*
  2172.  * prt_line() - print the given line
  2173.  */
  2174. void
  2175. prt_line(s)
  2176.     char           *s;
  2177. {
  2178.     register int    si = 0;
  2179.     register int    c;
  2180.     register int    col = 0;
  2181.  
  2182.     char            extra[16];
  2183.     int             n_extra = 0;
  2184.     int             n;
  2185.  
  2186.     for (;;) {
  2187.  
  2188.     if (n_extra > 0)
  2189.         c = extra[--n_extra];
  2190.     else {
  2191.         c = s[si++];
  2192.         if (c == TAB && !P(P_LS)) {
  2193.         strcpy(extra, "                ");
  2194.         /* tab amount depends on current column */
  2195.         n_extra = (P(P_TS) - 1) - col % P(P_TS);
  2196.         c = ' ';
  2197.         } else if (c == NUL && P(P_LS)) {
  2198.         extra[0] = NUL;
  2199.         n_extra = 1;
  2200.         c = '$';
  2201.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  2202.         char           *p;
  2203.  
  2204.         n_extra = 0;
  2205.         p = chars[c].ch_str;
  2206.         /* copy 'ch-str'ing into 'extra' in reverse */
  2207.         while (n > 1)
  2208.             extra[n_extra++] = p[--n];
  2209.         c = p[0];
  2210.         }
  2211.     }
  2212.  
  2213.     if (c == NUL)
  2214.         break;
  2215.  
  2216.     outchar(c);
  2217.     col++;
  2218.     }
  2219. }
  2220.  
  2221. void
  2222. screenclear()
  2223. {
  2224.     register char  *rp;
  2225.     register char  *np;
  2226.     register char  *end;
  2227.     register int    i;
  2228.  
  2229.     outstr(T_ED);        /* clear the display */
  2230.  
  2231.     rp = Realscreen;
  2232.     end = Realscreen + Rows * Columns;
  2233.     np = Nextscreen;
  2234.  
  2235.     /* blank out the stored screens */
  2236.     while (rp != end)
  2237.     *rp++ = *np++ = ' ';
  2238.  
  2239.     /* clear screen info */
  2240.     for (i = 0; i < Rows; i++) {
  2241.     LinePointers[i] = NULL;
  2242.     LineSizes[i] = '\0';
  2243.     }
  2244.     NumLineSizes = 0;
  2245. }
  2246.  
  2247. void
  2248. cursupdate()
  2249. {
  2250.     LPtr           *p;
  2251.     LPtr           *pp;
  2252.     char            c;
  2253.     int             incr, nlines;
  2254.     int             i;
  2255.     int             didincr;
  2256.  
  2257.     if (bufempty()) {        /* special case - file is empty */
  2258.     *Topchar = *Filemem;
  2259.     *Curschar = *Filemem;
  2260.     for (i = 0; i < Rows; i++)
  2261.         LineSizes[i] = 0;
  2262.     } else if (LINEOF(Curschar) < LINEOF(Topchar)) {
  2263.     nlines = cntllines(Curschar, Topchar);
  2264.     /*
  2265.      * if the cursor is above the top of the screen, put it at the top of
  2266.      * the screen.. 
  2267.      */
  2268.     *Topchar = *Curschar;
  2269.     Topchar->index = 0;
  2270.     /*
  2271.      * ... and, if we weren't very close to begin with, we scroll so that
  2272.      * the line is close to the middle. 
  2273.      */
  2274.     if (nlines > Rows / 3) {
  2275.         p = Topchar;
  2276.         for (i = 0; i < Rows / 3; i += plines(p)) {
  2277.         pp = prevline(p);
  2278.         if (pp == NULL)
  2279.             break;
  2280.         p = pp;
  2281.         }
  2282.         *Topchar = *p;
  2283.     } else
  2284.         s_ins(0, nlines - 1, Rows, Columns);
  2285.     updateNextscreen(VALID);
  2286.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  2287.     nlines = cntllines(Botchar, Curschar);
  2288.     /*
  2289.      * If the cursor is off the bottom of the screen, put it at the top
  2290.      * of the screen.. ... and back up 
  2291.      */
  2292.     if (nlines > Rows / 3) {
  2293.         p = Curschar;
  2294.         for (i = 0; i < (2 * Rows) / 3; i += plines(p)) {
  2295.         pp = prevline(p);
  2296.         if (pp == NULL)
  2297.             break;
  2298.         p = pp;
  2299.         }
  2300.         *Topchar = *p;
  2301.     } else {
  2302.         scrollup(nlines);
  2303.     }
  2304.     updateNextscreen(VALID);
  2305.     }
  2306.     Cursrow = Curscol = Cursvcol = i = 0;
  2307.     for (p = Topchar; p->linep != Curschar->linep; p = nextline(p))
  2308.     Cursrow += LineSizes[i++];
  2309.  
  2310.     if (P(P_NU))
  2311.     Curscol = 8;
  2312.  
  2313.     Cline_row = Cursrow;
  2314.     if (i >= NumLineSizes) {    /* Should only happen with a line that is too
  2315.                  * long to fit on the last screen line. */
  2316.     Cline_size = 0;
  2317.     } else {
  2318.     Cline_size = LineSizes[i];
  2319.  
  2320.     for (i = 0; i <= Curschar->index; i++) {
  2321.         c = Curschar->linep->s[i];
  2322.         /* A tab gets expanded, depending on the current column */
  2323.         if (c == TAB && !P(P_LS))
  2324.         incr = P(P_TS) - (Cursvcol % P(P_TS));
  2325.         else
  2326.         incr = chars[c].ch_size;
  2327.         Curscol += incr;
  2328.         Cursvcol += incr;
  2329.         if (Curscol >= Columns) {
  2330.         Curscol -= Columns;
  2331.         Cursrow++;
  2332.         didincr = TRUE;
  2333.         } else
  2334.         didincr = FALSE;
  2335.     }
  2336.     if (didincr)
  2337.         Cursrow--;
  2338.  
  2339.     if (c == TAB && State == NORMAL && !P(P_LS)) {
  2340.         Curscol--;
  2341.         Cursvcol--;
  2342.     } else {
  2343.         Curscol -= incr;
  2344.         Cursvcol -= incr;
  2345.     }
  2346.     if (Curscol < 0)
  2347.         Curscol += Columns;
  2348.     }
  2349.  
  2350.     if (set_want_col) {
  2351.     Curswant = Cursvcol;
  2352.     set_want_col = FALSE;
  2353.     }
  2354. }
  2355.  
  2356. /*
  2357.  * The rest of the routines in this file perform screen manipulations. The
  2358.  * given operation is performed physically on the screen. The corresponding
  2359.  * change is also made to the internal screen image. In this way, the editor
  2360.  * anticipates the effect of editing changes on the appearance of the screen.
  2361.  * That way, when we call screenupdate a complete redraw isn't usually
  2362.  * necessary. Another advantage is that we can keep adding code to anticipate
  2363.  * screen changes, and in the meantime, everything still works. 
  2364.  */
  2365.  
  2366. /*
  2367.  * s_ins(row, nlines, total_rows, columns) - insert 'nlines' lines at 'row' 
  2368.  */
  2369. void
  2370. s_ins(row, nlines, total_rows, columns)
  2371.     int             row;
  2372.     int             nlines;
  2373.     int            total_rows;
  2374.     int            columns;
  2375. {
  2376.     register char  *s;    /* src for block copy */
  2377.     register char  *d;    /* dest for block copy */
  2378.     register char  *e;    /* end point for copy */
  2379.     int             i;
  2380.  
  2381.     if (nlines > (total_rows - 1 - row))
  2382.     nlines = total_rows - 1 - row;
  2383.  
  2384.     if ((T_IL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  2385.     return;
  2386.  
  2387.     /*
  2388.      * It "looks" better if we do all the inserts at once 
  2389.      */
  2390.     outstr(T_SC);        /* save position */
  2391.  
  2392.     if (T_IL_B[0] == NUL) {
  2393.     for (i = 0; i < nlines; i++) {
  2394.         windgoto(row, 0);
  2395.         outstr(T_IL);
  2396.     }
  2397.     } else {
  2398.     windgoto(row, 0);
  2399.     outstr(T_IL);
  2400.     if (nlines >= 10)
  2401.         outchar((char) (nlines / 10 + '0'));
  2402.     outchar((char) (nlines % 10 + '0'));
  2403.     outstr(T_IL_B);
  2404.     }
  2405.  
  2406.     windgoto(total_rows - 1, 0);    /* delete any garbage that may have */
  2407.     outstr(T_EL);        /* been shifted to the bottom line */
  2408.  
  2409.     outstr(T_RC);        /* restore the cursor position */
  2410.  
  2411.     /*
  2412.      * Now do a block move to update the internal screen image 
  2413.      */
  2414.     d = Realscreen + (columns * (total_rows - 1)) - 1;
  2415.     s = d - (columns * nlines);
  2416.     e = Realscreen + (columns * row);
  2417.  
  2418.     while (s >= e)
  2419.     *d-- = *s--;
  2420.  
  2421.     /*
  2422.      * Clear the inserted lines 
  2423.      */
  2424.     s = Realscreen + (row * columns);
  2425.     e = s + (nlines * columns);
  2426.     while (s < e)
  2427.     *s++ = ' ';
  2428. }
  2429.  
  2430. /*
  2431.  * s_del(row, nlines, total_rows, columns) - delete 'nlines' lines at 'row' 
  2432.  */
  2433. void
  2434. s_del(row, nlines, total_rows, columns)
  2435.     int             row;
  2436.     int             nlines;
  2437.     int            total_rows;
  2438.     int            columns;
  2439. {
  2440.     register char  *s;
  2441.     register char  *d;
  2442.     register char  *e;
  2443.     int             i;
  2444.  
  2445.     if (nlines > (total_rows - 1 - row))
  2446.     nlines = total_rows - 1 - row;
  2447.  
  2448.     if ((T_DL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  2449.     return;
  2450.  
  2451.     outstr(T_SC);        /* save position */
  2452.  
  2453.     windgoto(total_rows - 1, 0);    /* delete any garbage that */
  2454.     outstr(T_EL);        /* was on the status line */
  2455.  
  2456.     /* delete the lines */
  2457.     if (T_DL_B[0] == NUL) {
  2458.     for (i = 0; i < nlines; i++) {
  2459.         windgoto(row, 0);
  2460.         outstr(T_DL);    /* delete a line */
  2461.     }
  2462.     } else {
  2463.     windgoto(row, 0);
  2464.     outstr(T_DL);
  2465.     if (nlines >= 10)
  2466.         outchar((char) (nlines / 10 + '0'));
  2467.     outchar((char) (nlines % 10 + '0'));
  2468.     outstr(T_DL_B);
  2469.     }
  2470.  
  2471.     outstr(T_RC);        /* restore position */
  2472.  
  2473.     /*
  2474.      * do a block move to update the internal image 
  2475.      */
  2476.     d = Realscreen + (row * columns);
  2477.     s = d + (nlines * columns);
  2478.     e = Realscreen + ((total_rows - 1) * columns);
  2479.  
  2480.     while (s < e)
  2481.     *d++ = *s++;
  2482.  
  2483.     while (d < e)        /* clear the lines at the bottom */
  2484.     *d++ = ' ';
  2485. }
  2486. SHAR_EOF
  2487. #    End of shell archive
  2488. exit 0
  2489. -- 
  2490. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2491. Have five nice days.
  2492.